
import asyncio
import uuid
from asyncio import Queue
from sqlalchemy import insert, delete, text, select, update, desc
from initialization.crudInit import insert_pojo_by_relation, update_pojo_by_relation
from model.entitys import Menu, RoleMenu, UserRole, User, Role
from utils.decorator import transaction_decorator, analysis_token_decorator

@transaction_decorator
async def add_user(session, user):
    user["id"] = uuid.uuid1().__str__()
    await insert_pojo_by_relation(session, User, user, "roleList", UserRole, "userId", "roleId")

@transaction_decorator
async def add_role(session, role):
    role["id"] = uuid.uuid1().__str__()
    await insert_pojo_by_relation(session, Role, role, "menuList", RoleMenu, "roleId", "menuId")

@transaction_decorator
async def add_role_v1(session, role):
    r = Role()
    r.id = uuid.uuid1().__str__()
    r.name = role.name
    r.remarks = role.remarks
    session.add(r)

    await update_role_menu_by_role_id(session, r.id, role.menuList, 0)

@transaction_decorator
async def update_user(session, user):
    await update_pojo_by_relation(session, User, user, "roleList", UserRole, "userId", "roleId")

async def query_children_menu_list(session, menu, role_id_list):
    menu.menuList = (await session.execute(select(Menu).where(Menu.parentId == menu.id))).scalars().all()
    for children in menu.menuList:
        rm = (await session.execute(select(RoleMenu).where(RoleMenu.roleId.in_(role_id_list)).where(RoleMenu.menuId == children.id))).scalars().all()
        if len(rm) != 0:
            children.thisRoleMenu = True
        else:
            children.thisRoleMenu = False

        await query_children_menu_list(session, children, role_id_list)

async def query_menu_by_role_id(session, role_id):
    menuList = (await session.execute(select(Menu).where(Menu.parentId == None))).scalars().all()
    for menu in menuList:
        rm = (await session.execute(select(RoleMenu).where(RoleMenu.roleId.in_((role_id,))).where(RoleMenu.menuId == menu.id))).scalars().all()
        if len(rm) != 0:
            menu.thisRoleMenu = True
        else:
            menu.thisRoleMenu = False

        await query_children_menu_list(session, menu, (role_id,))

    await session.close()

    return {"message": "查询成功", "code": 200, "data": menuList}

# 强行异步智障写法
async def query_children_menu_number(session, menu, queue):
    await queue.put(menu.id)

    menu.menuList = (await session.execute(select(Menu).where(Menu.parentId == menu.id))).scalars().all()
    for children in menu.menuList:
        await query_children_menu_number(session, children, queue)

async def query_children_menu_list_async(session, menu, role_id_list, queue):
    menu.menuList = (await session.execute(select(Menu).where(Menu.parentId == menu.id))).scalars().all()
    for children in menu.menuList:
        rm = (await session.execute(select(RoleMenu).where(RoleMenu.roleId.in_(role_id_list)).where(RoleMenu.menuId == children.id))).scalars().all()
        if len(rm) != 0:
            children.thisRoleMenu = True
        else:
            children.thisRoleMenu = False

        asyncio.create_task(query_children_menu_list_async(session, children, role_id_list, queue))

    await queue.get()
    queue.task_done()

async def query_menu_by_role_id_async(session, role_id):
    queue = Queue()
    menu_list = (await session.execute(select(Menu).where(Menu.parentId == None))).scalars().all()

    for menu in menu_list:
        await query_children_menu_number(session, menu, queue)

    for menu in menu_list:
        rm = (await session.execute(select(RoleMenu).where(RoleMenu.roleId.in_((role_id,))).where(RoleMenu.menuId == menu.id))).scalars().all()
        if len(rm) != 0:
            menu.thisRoleMenu = True
        else:
            menu.thisRoleMenu = False

        asyncio.create_task(query_children_menu_list_async(session, menu, (role_id,), queue))

    await queue.join()

    await session.close()

    return {"message": "查询成功", "code": 200, "data": menu_list}

@transaction_decorator
async def update_role_menu_by_role_id_api(session, roleId, menuList, c):
    await update_role_menu_by_role_id(session, roleId, menuList, c)

async def update_role_menu_by_role_id(session, roleId, menuList, c):
    for menu in menuList:
        if c == 0:
            rm = (await session.execute(select(RoleMenu).where(RoleMenu.roleId == roleId).where(RoleMenu.menuId == menu.id))).scalars().first()

            if menu.thisRoleMenu == True:
                if rm == None:
                    nrm = RoleMenu()
                    nrm.id = uuid.uuid1().__str__()
                    nrm.roleId = roleId
                    nrm.menuId = menu.id
                    session.add(nrm)

            else:
                if rm != None:
                    await session.execute(delete(RoleMenu).where(RoleMenu.roleId == roleId).where(RoleMenu.menuId == menu.id))

            await update_role_menu_by_role_id(session, roleId, menu.menuList, c + 1)

        else:
            rm = (await session.execute(select(RoleMenu).where(RoleMenu.roleId == roleId).where(RoleMenu.menuId == menu["id"]))).scalars().first()

            if menu["thisRoleMenu"] == True:
                if rm == None:
                    nrm = RoleMenu()
                    nrm.id = uuid.uuid1().__str__()
                    nrm.roleId = roleId
                    nrm.menuId = menu["id"]
                    session.add(nrm)

            else:
                if rm != None:
                    await session.execute(delete(RoleMenu).where(RoleMenu.roleId == roleId).where(RoleMenu.menuId == menu["id"]))

            await update_role_menu_by_role_id(session, roleId, menu["menuList"], c+1)

# 强行异步智障写法
@transaction_decorator
async def update_role_menu_by_role_id_api_async(session, roleId, menu_list):
    queue = Queue()
    await fund_menu_number(session, menu_list, queue)

    asyncio.create_task(update_role_menu_by_role_id_async(session, roleId, menu_list, queue))

    await queue.join()

async def fund_menu_number(session, menu_list, queue):
    for menu in menu_list:
        await queue.put(menu["id"])

        await fund_menu_number(session, menu["menuList"], queue)

async def update_role_menu_by_role_id_async(session, role_id, menu_list, queue):
    for menu in menu_list:
        rm = (await session.execute(select(RoleMenu).where(RoleMenu.roleId == role_id).where(RoleMenu.menuId == menu["id"]))).scalars().first()

        if menu["thisRoleMenu"] == True:
            if rm == None:
                nrm = RoleMenu()
                nrm.id = uuid.uuid1().__str__()
                nrm.roleId = role_id
                nrm.menuId = menu["id"]
                session.add(nrm)

        else:
            if rm != None:
                await session.execute(delete(RoleMenu).where(RoleMenu.roleId == role_id).where(RoleMenu.menuId == menu["id"]))

        asyncio.create_task(update_role_menu_by_role_id_async(session, role_id, menu["menuList"], queue))

        await queue.get()
        queue.task_done()

async def query_menu_by_user_id(session, user_id):
    roleIdAll = (await session.execute(select(UserRole.roleId).where(UserRole.userId == user_id))).scalars().all()

    menuList = (await session.execute(select(Menu).where(Menu.parentId == None))).scalars().all()
    for menu in menuList:
        rm = (await session.execute(
            select(RoleMenu).where(RoleMenu.roleId.in_(roleIdAll)).where(RoleMenu.menuId == menu.id))).scalars().all()
        if len(rm) != 0:
            menu.thisRoleMenu = True
        else:
            menu.thisRoleMenu = False

        await query_children_menu_list(session, menu, roleIdAll)

    await session.close()

    return {"message": "查询成功", "code": 200, "data": menuList}

# 强行异步智障写法
async def query_menu_by_user_id_async(session, user_id):
    role_id_all = (await session.execute(select(UserRole.roleId).where(UserRole.userId == user_id))).scalars().all()

    task_list = []
    menu_list = (await session.execute(select(Menu).where(Menu.parentId == None))).scalars().all()
    for menu in menu_list:
        rm = (await session.execute(
            select(RoleMenu).where(RoleMenu.roleId.in_(role_id_all)).where(RoleMenu.menuId == menu.id))).scalars().all()
        if len(rm) != 0:
            menu.thisRoleMenu = True
        else:
            menu.thisRoleMenu = False

        task_list.append(asyncio.create_task(query_children_menu_list(session, menu, role_id_all)))

    await asyncio.wait(task_list)

    await session.close()

    return {"message": "查询成功", "code": 200, "data": menu_list}

async def get_user_children(session, menu, user_id):
    menu.menuList = (await session.execute(select(Menu).distinct().\
                      join(RoleMenu, RoleMenu.menuId == Menu.id).\
                      join(UserRole, UserRole.roleId == RoleMenu.roleId).\
                      where(UserRole.userId == user_id).\
                      where(Menu.parentId == menu.id))).scalars().all()

    for children in menu.menuList:
        await get_user_children(session, children, user_id)

@analysis_token_decorator
async def get_user_menu(session, user_id):
    menuList = (await session.execute(select(Menu).distinct().\
                      join(RoleMenu, RoleMenu.menuId == Menu.id).\
                      join(UserRole, UserRole.roleId == RoleMenu.roleId).\
                      where(UserRole.userId == user_id).\
                      where(Menu.parentId == None))).scalars().all()

    for menu in menuList:
        await get_user_children(session, menu, user_id)

    await session.close()

    return {"message": "查询成功", "code": 200, "data": menuList}





























